namespace C4F.DevKit.Bluetooth
{
    namespace ServiceAndDeviceDiscovery
    {
        #region Using Directives
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Net;
        using System.Net.Sockets;
        #endregion

        /// <summary>
        /// Creates an endpoint for a service
        /// </summary>

        public class BluetoothEndPoint : System.Net.EndPoint
        {
            #region Private Members

            /// <summary>
            /// Represents the device address
            /// </summary>
            BluetoothSocketAddress address;

            /// <summary>
            /// Represents the guid of the service on remote device.
            /// </summary>
            Guid servClassGuid;

            /// <summary>
            /// Represents the port number
            /// </summary>
            int portNo;

            #endregion

            #region Constructors

            /// <summary>
            /// Initializes a Bluetooth endpoint object
            /// </summary>
            
            public BluetoothEndPoint()
            {
            }

            /// <summary>
            /// Initializes a Bluetooth endpoint object.
            /// </summary>
            /// <param name="device">Represents the remote device to connect to.</param>
            /// <param name="serviceClassGuid">Represents the guid of the service
            /// on remote device.</param>
            
            public BluetoothEndPoint(Device device, Guid serviceClassGuid)                                   
            {
                this.address = device.Address;
                this.servClassGuid = serviceClassGuid;
                this.portNo = BluetoothHelper.ANY_CHANNEL;
            }

            /// <summary>
            ///Initializes a Bluetooth endpoint object
            /// </summary>
            /// <param name="deviceAddress">Represents the remote device address.
            /// </param>
            /// <param name="serviceClassGuid">Represents the guid of the service
            /// on remote device.</param>
            public BluetoothEndPoint(BluetoothSocketAddress deviceAddress, 
                                     Guid serviceClassGuid)
            {
                this.address = deviceAddress;
                this.servClassGuid = serviceClassGuid;
                this.portNo = BluetoothHelper.ANY_CHANNEL;
            }

            /// <summary>
            /// Initializes a Bluetooth endpoint object
            /// </summary>
            /// <param name="deviceAddress">Represents the remote device address.
            /// </param>
            /// <param name="serviceClassGuid">Represents the guid of the service
            /// on remote device.</param>
            /// <param name="port">Represents the port on remote device.</param>
            
            public BluetoothEndPoint(BluetoothSocketAddress deviceAddress, 
                                     Guid serviceClassGuid, 
                                     int port)
            {
                this.address = deviceAddress;
                this.servClassGuid = serviceClassGuid;
                this.portNo = port;
            }
            #endregion

            #region Internal Properties

            /// <summary>
            /// Gets the port number
            /// </summary>
            internal int Port
            {
                get
                {
                    return portNo;
                }
            }

            /// <summary>
            /// Gets the service class id of the service.
            /// </summary>
            internal Guid ServiceClassGuid
            {
                get
                {
                    return servClassGuid;
                }
            }

            /// <summary>
            /// Gets the address of device.
            /// </summary>
            internal BluetoothSocketAddress Address
            {
                get
                {
                    return address;
                }
            }

            #endregion

            #region Public Functions

            /// <summary>
            /// Creates a socket address by using the port, serviceClass Guid and 
            /// address variable values
            /// </summary>
            /// <returns>Returns a socket address</returns>
            public override System.Net.SocketAddress Serialize()
            {                
                System.Net.SocketAddress socketAddress = 
                    new System.Net.SocketAddress(AddressFamily.Unspecified, 
                                        BluetoothHelper.SOCKET_ADDRESS_LENGTH);

                // AddressFamily is the same for both CE and XP
                socketAddress[0] = 32;

                // copy in the remote bt address
                byte[] addr = BitConverter.GetBytes(address.Address);
                for (int i = 0; i < addr.Length; i++)
                    socketAddress[BluetoothHelper.ADDRESS_OFFSET + i] = 
                                                                addr[i];

                // copy in the guid of the service we want to connect with
                byte[] guidArray = servClassGuid.ToByteArray();

                for (int i = 0; i < 16; i++)
                    socketAddress[BluetoothHelper.GUID_OFFSET + i] = 
                                                            guidArray[i];

                // copy in the channel number that we would like this 
                //connection to use
                byte[] portAsBytes = BitConverter.GetBytes(portNo);

                for (int i = 0; i < 4; i++)
                    socketAddress[BluetoothHelper.CHANNEL_OFFSET + i] = 
                                                            portAsBytes[i];

                return socketAddress;
            }

            /// <summary>
            /// Creates an endpoint from the specified socket address.
            /// </summary>
            /// <param name="socketAddress">The socket address that serves as 
            /// the endpoint for a connection.</param>
            /// <returns>A new EndPoint instance that is initialized from the 
            /// specified SocketAddress instance.</returns>
            
            public override System.Net.EndPoint Create(
                                      System.Net.SocketAddress socketAddress) 
            {
                // device Address
                byte[] addr = new byte[8];
                for (int i = 0; i < 8; i++)
                    addr[i] = socketAddress[BluetoothHelper.ADDRESS_OFFSET 
                                            + i];

                // guid
                byte[] serviceClassGuid = new byte[16];
                for (int i = 0; i < 16; i++)
                    serviceClassGuid[i] = socketAddress[
                                          BluetoothHelper.GUID_OFFSET + i];

                byte[] deviceAddr = addr;
                Guid guidValue = new Guid(serviceClassGuid);
                //Guid g = _serviceGuid;
                // port number
                byte[] portNumArray = new byte[4];
                for (int i = 0; i < 4; i++)
                    portNumArray[i] = socketAddress[
                                      BluetoothHelper.CHANNEL_OFFSET + i];

                BluetoothSocketAddress bthAddr = new BluetoothSocketAddress();
                bthAddr.AddressFamily = (ushort)socketAddress.Family;
                bthAddr.Port = (uint)BitConverter.ToInt32(portNumArray, 0); 
                bthAddr.ServiceClassId = guidValue;
                bthAddr.Address = (ulong)BitConverter.ToInt64(addr, 0);

                return new BluetoothEndPoint(bthAddr, guidValue, 
                                            (int)bthAddr.Port);
            }

            #endregion
            
        }
    }
}